package com.example.springboot.config.拦截器;


import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * 编写拦截器  注册到容器中
 * 登录检查
 * 1.配置好拦截器要拦截哪些请求
 * 2.把这些配置放在容器中
 *
 * 拦截器执行的位置
 * 第一次  控制器方法之前
 * 第二次  控制器方法之后
 * 第三次  视图渲染完毕之后
 * interceptor  拦截器
 * ctrl+o  可以快捷添加重写的方法
 *
 * 2、拦截器的三个抽象方法
 * SpringMVC中的拦截器有三个抽象方法:
 * preHandle:控制器方法执行之前执行preHandle,
 *           其boolean类型的返回值表示是否拦截或放行，
 *           返回true为放行，即调用控制器方法;
 *           返回false表示拦截，即不调用控制器方法
 * postHandle:控制器方法执行之后执行postHandle
 * afterCompletion:
 *        处理完视图和模型数据，渲染视图完毕之后执行 afterCompletion()
 *
 * 3、多个拦截器的执行顺序
 * a>若每个拦截器的preHandle()都返回true
 *    此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:
 *     preHandle()会按照配置的顺序执行，
 *    而postHandle()和afterCompletion()会按照配置的反序执行
 * b>若某个拦截器的preHandle()返回了false
 *     preHandle()返回false和它之前的拦截器的preHandle()都会执行，
 *     postHandle()都不执行，
 *     返回false的拦截器之前的拦截器的 afterCompletion()会执行
 *
 * 多个拦截器的执行顺序： 根据配置顺序  在 HandlerExecutionChain类中
 * 假设3个拦截器  1个spring自带 2个手写的
 * * preHandle   按顺序  进入 applyPreHandle 方法   interceptorIndex   从0开始  循环赋值
 * 		    for (int i = 0; i < this.interceptorList.size(); i++) {
 * 		    	HandlerInterceptor interceptor = this.interceptorList.get(i);
 * 		    	if (!interceptor.preHandle(request, response, this.handler)) {
 * 		    		triggerAfterCompletion(request, response, null);//会进入第三个拦截器
 * 		    		return false;
 *                  }
 * 		    	this.interceptorIndex = i;
 * 		    }
 * 		    return true;
 *
 * * postHandle  按反序 进入 applyPostHandle 方法 从拦截器数组.length-1  到0
 *
 *       for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
 * 	    		HandlerInterceptor interceptor = this.interceptorList.get(i);
 * 	    		interceptor.postHandle(request, response, this.handler, mv);
 *       }
 *
 *
 * * afterCompletion    按反序 进入 triggerAfterCompletion 方法   interceptorIndex   减减   到0
 *       for (int i = this.interceptorIndex; i >= 0; i--) {
 *      			HandlerInterceptor interceptor = this.interceptorList.get(i);
 *      			try {
 *      				interceptor.afterCompletion(request, response, this.handler, ex);
 *               }catch (Throwable ex2) {
 *      				logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
 *               }
 *        }
 *
 */
@Slf4j//日志
public class 防登录 implements HandlerInterceptor {//防登录

    /**
     * 目标方法执行完成以前
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException, ServletException {
        //登录检查逻辑
        HttpSession session = request.getSession();
        Object loginUser = session.getAttribute("loginUser");
        if(true){
            return true;//放行
        }
        if(loginUser!=null){
            return true;//放行
        }
        request.setAttribute("msg","你没有登录");
        request.getRequestDispatcher("/login")//转发
                .forward(request,response);

        return false;//拦截
    }

    /**
     * 目标方法执行完成以后
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) {
    }

    /**
     * 页面渲染之后
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}
